package com.atguigu.tingshu.payment.strategy.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.account.client.RechargeInfoFeignClient;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AssertUtil;
import com.atguigu.tingshu.model.account.RechargeInfo;
import com.atguigu.tingshu.payment.config.WxPayV3Config;
import com.atguigu.tingshu.payment.service.PaymentInfoService;
import com.atguigu.tingshu.payment.strategy.PayTypeStrategy;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

//充值支付策略
@Component(value = SystemConstant.PAYMENT_TYPE_RECHARGE)
public class RechargePayStrategy implements PayTypeStrategy {
    @Autowired
    private PaymentInfoService paymentInfoService;
    @Autowired
    private RSAAutoCertificateConfig rsaAutoCertificateConfig;
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private WxPayV3Config wxPayV3Config;
    @Autowired
    private RechargeInfoFeignClient rechargeInfoFeignClient;
//    @Autowired
//    private RabbitTemplate rabbitTemplate;
    @Override
    public JSONObject createJsapi(String payType, String orderNo) {
        //0.1 判断充值记录的支付状态：
        Result<RechargeInfo> rechargeInfoResult = rechargeInfoFeignClient.getRechargeByOrderNo(orderNo);
        AssertUtil.resultAssert(rechargeInfoResult , ResultCodeEnum.DATA_ERROR);
        RechargeInfo rechargeInfo = rechargeInfoResult.getData();
        if(!rechargeInfo.getRechargeStatus().equals(SystemConstant.ORDER_STATUS_UNPAID)){
            throw new GuiguException(ResultCodeEnum.DATA_ERROR);
        }
        //0.2 保存预支付的交易日志，支付成功时可以更新交易日志状态为成功
        //--1 先查询交易日志
        paymentInfoService.savePaymentInfo(payType, orderNo, rechargeInfo);
        // 使用自动更新平台证书的RSA配置
        // 建议将 config 作为单例或全局静态对象，避免重复的下载浪费系统资源
        //1、获取配置对象：RSAAutoCertificateConfig
        //2、构建service：可以访问wx后端结构 生成预支付订单
        //NativePayService: 二维码方式生成预支付
        //JsapiServiceExtension: jsapi方式  生成 客户端支付(拉起前端wx收银台)的预支付订单
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig)
                .build();
        //2.1 为service准备预支付的参数
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();//预支付的订单金额
        amount.setTotal(1);//单位分
        request.setAmount(amount);
        request.setMchid(wxPayV3Config.getMerchantId());
        request.setAppid(wxPayV3Config.getAppid());
        request.setDescription("充值："+rechargeInfo.getRechargeAmount()+" 元"); //需要查询
        request.setOutTradeNo(orderNo);//
        request.setNotifyUrl(wxPayV3Config.getNotifyUrl());
        //配置支付者信息：必须携带
        Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfo(rechargeInfo.getUserId());
        AssertUtil.resultAssert(userInfoVoResult,ResultCodeEnum.DATA_ERROR);
        UserInfoVo userInfoVo = userInfoVoResult.getData();
        Payer payer = new Payer();
        payer.setOpenid(userInfoVo.getWxOpenId());//获取当前用户的openId设置
        request.setPayer(payer);

        //2.2 传入预支付的参数使用service向wx服务端发起请求 得到wx预支付订单的响应
        PrepayWithRequestPaymentResponse response = service
                .prepayWithRequestPayment(request);

        //3、解析预支付的响应 封装客户端需要的参数(客户端根据参数 调起前端wx支付)
        //appId   timeStamp  nonceStr  package  signType paySign
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appId",response.getAppId());
        jsonObject.put("timeStamp",response.getTimeStamp());
        jsonObject.put("nonceStr",response.getNonceStr());
        jsonObject.put("package",response.getPackageVal());
        jsonObject.put("signType",response.getSignType());
        jsonObject.put("paySign",response.getPaySign());
        return jsonObject;
    }

    @Override
    public void wxNotify(Transaction transaction) {
        //更新充值记录的状态
        //添加账户余额
        String orderNo = transaction.getOutTradeNo();
        String orderStatus = transaction.getTradeState().equals(Transaction.TradeStateEnum.SUCCESS)
                ?SystemConstant.ORDER_STATUS_PAID:SystemConstant.ORDER_STATUS_FAIL;
        Result<Boolean> result = rechargeInfoFeignClient.updateRechargeByOrderNo(orderNo, orderStatus);
        AssertUtil.resultAssert(result , ResultCodeEnum.DATA_ERROR);

    }
}
